<!-- ===========================================================
================================================================
=== Element UI 表格封装 ==========================================
=== https://rad.huice.com/zh-CN/component/table.html ===========
================================================================
============================================================ -->
<template>

  <div class="fly-table-container">

    <!--  搜索  -->
    <div class="table-search-container">
      <table-search :searchField="searchField" :showCol="searchShowCol" @search="onSearch"></table-search>
    </div>


    <!--  表头操作工具栏，例如：新增  -->
    <div class="fly-tool-bar">
      <slot name="tableHeader"/>
    </div>


    <!--  表格数据展示  -->
    <div class="fly-el-table-container">
      <div class="table-container">
        <el-table :data="data.rows"
                  :border="setBorder"
                  v-bind="$attrs"
                  row-key="id"
                  stripe
                  style="width: 100%"
                  v-loading="config.loading"
                  @selection-change="onSelectionChange">

          <el-table-column type="selection" :reserve-selection="true" align="center" width="40"
                           v-if="config.isSelection"/>
          <el-table-column type="index" label="序号" align="center" width="70" v-if="config.isSerialNo"/>

          <el-table-column v-for="(item, index) in setHeader"
                           :key="index"
                           show-overflow-tooltip
                           :align="item.align ? item.align : 'center '"
                           :prop="item.key"
                           :width="item.colWidth"
                           :label="item.title">


            <template v-slot="scope">

              <template v-if="item.type === 'image'">
                <el-image :style="{ width: `${item.width}px`, height: `${item.height}px` }"
                          :src="scope.row[item.key]"
                          :zoom-rate="1.2"
                          :preview-src-list="[scope.row[item.key]]"
                          preview-teleported
                          fit="cover"/>
              </template>
              <template v-else>
                {{ scope.row[item.key] }}
              </template>
            </template>
          </el-table-column>

          <el-table-column label="操作" fixed="right" align="center" width="400" v-if="config.isOperate">
            <slot name="toolBar"/>
          </el-table-column>


          <template #empty>
            <el-empty description="暂无数据"/>
          </template>
        </el-table>


        <div class="table-footer mt15 fly-pagination">
          <el-pagination v-model:current-page="state.page.page"
                         v-model:page-size="state.page.limit"
                         :pager-count="5"
                         :page-sizes="[10, 20, 30, 50, 100]"
                         :total="data.total"
                         :small="true"
                         prev-text="上一页"
                         next-text="下一页"
                         layout="total, sizes, prev, pager, next, jumper"
                         background
                         @size-change="onHandleSizeChange"
                         @current-change="onHandleCurrentChange">


          </el-pagination>
          <div class="table-footer-tool">
            <SvgIcon name="iconfont icon-dayin" :size="19" title="打印" @click="onPrintTable"/>
            <SvgIcon name="iconfont icon-yunxiazai_o" :size="22" title="导出" @click="onImportTable"/>
            <SvgIcon name="iconfont icon-shuaxin" :size="22" title="刷新" @click="onRefreshTable"/>
            <el-popover placement="top-end"
                        trigger="click"
                        transition="el-zoom-in-top"
                        popper-class="table-tool-popper"
                        :width="300"
                        :persistent="false"
                        @show="onSetTable">
              <template #reference>
                <SvgIcon name="iconfont icon-quanjushezhi_o" :size="22" title="设置"/>
              </template>
              <template #default>
                <div class="tool-box">

                  <el-tooltip content="拖动进行排序" placement="top-start">
                    <SvgIcon name="fa fa-question-circle-o" :size="17" class="ml11" color="#909399"/>
                  </el-tooltip>

                  <el-checkbox v-model="state.checkListAll"
                               :indeterminate="state.checkListIndeterminate"
                               class="ml10 mr1"
                               label="列显示"
                               @change="onCheckAllChange"/>
                  <el-checkbox v-model="getConfig.isSerialNo" class="ml12 mr1" label="序号"/>
                  <el-checkbox v-model="getConfig.isSelection" class="ml12 mr1" label="多选"/>
                </div>
                <el-scrollbar>
                  <div ref="toolSetRef" class="tool-sortable">
                    <div class="tool-sortable-item" v-for="v in columns" :key="v.key" :data-key="v.key">
                      <i class="fa fa-arrows-alt handle cursor-pointer"></i>
                      <el-checkbox size="default" class="ml12 mr8"
                                   v-model="v.isCheck"
                                   :label="v.title"
                                   @change="onCheckChange"/>
                    </div>
                  </div>
                </el-scrollbar>


              </template>
            </el-popover>
          </div>
        </div>
      </div>


    </div>


  </div>


</template>


<script setup lang="ts" name="FlyTable">
import {onMounted, computed, nextTick, reactive, ref} from "vue";
import {Search, FolderAdd, Promotion, View, EditPen, Refresh, Delete} from '@element-plus/icons-vue';
import TableSearch from "/@/components/FlyTable/table/TableSearch.vue";
// import ElTable from "/@/components/FlyTable/table/ElTable.vue";

import {ElMessage} from 'element-plus';
import printJs from 'print-js';
import table2excel from 'js-table2excel';
import Sortable from 'sortablejs';
import {storeToRefs} from 'pinia';
import {useThemeConfig} from '/@/stores/themeConfig';
import '/@/theme/tableTool.scss';


const props = defineProps({
  data: {
    type: Object,
    default: () => {
      return {
        'total': 0,
        'rows': [],
      }
    },
  },

  searchField: {
    type: Array<TableSearchType>,
    default: () => [],
  },

  searchShowCol: {
    type: Number,
    default: 3,
  },

  // 表头内容
  columns: {
    type: Array<EmptyObjectType>,
    default: () => [],
  },

  // 配置项
  config: {
    type: Object,
    default: () => {
    },
  },

  params: {
    type: Object,
    default: () => {
      return {
        'page': 1,
        'limit': 10
      }
    },
  }


})


/**
 * 查询条件
 */
const queryParams = ref(props.params);

/**
 * 搜索点击时表单回调
 * @param data
 */
const onSearch = (data: EmptyObjectType) => {
  pageReset();
  /* 搜索时，给查询条件复制 */
  queryParams.value = Object.assign({}, props.params, {...data});
  onTapPageChange();
};


/**************** 表格 START ***********************************************************************************/


// 定义子组件向父组件传值/事件
const emit = defineEmits(['delRow', 'pageChange', 'sortHeader']);

// 定义变量内容
const toolSetRef = ref();
const storesThemeConfig = useThemeConfig();
const {themeConfig} = storeToRefs(storesThemeConfig);


const state = reactive({
  page: {
    page: 1,
    limit: 10,
  },
  selectlist: [] as EmptyObjectType[],
  checkListAll: true,
  checkListIndeterminate: false,
});

// 设置边框显示/隐藏
const setBorder = computed(() => {
  return props.config.isBorder ? true : false;
});

// 获取父组件 配置项（必传）
const getConfig = computed(() => {
  return props.config;
});


// 设置 tool header 数据
const setHeader = computed(() => {
  return props.columns.filter((v) => v.isCheck);
});


// tool 列显示全选改变时
const onCheckAllChange = <T>(val: T) => {
  console.log('onCheckAllChange val', val)
  if (val) props.columns.forEach((v) => (v.isCheck = true));
  else props.columns.forEach((v) => (v.isCheck = false));
  state.checkListIndeterminate = false;
};


// tool 列显示当前项改变时
const onCheckChange = () => {
  const headers = props.columns.filter((v) => v.isCheck).length;
  console.log('onCheckChange headers', headers)
  state.checkListAll = headers === props.columns.length;
  state.checkListIndeterminate = headers > 0 && headers < props.columns.length;
};


// 表格多选改变时，用于导出
const onSelectionChange = (val: EmptyObjectType[]) => {
  state.selectlist = val;
};


// 删除当前项
const onDelRow = (row: EmptyObjectType) => {
  emit('delRow', row);
};


// 修改每页查询多少条数据
const onHandleSizeChange = (val: number) => {
  state.page.limit = val;
  onTapPageChange();
};

// 上一页、下一页
const onHandleCurrentChange = (val: number) => {
  state.page.page = val;
  onTapPageChange();
};


// 搜索时，分页还原成默认
const pageReset = () => {
  state.page.page = 1;
  state.page.limit = 10;
  emit('pageChange', state.page);
};


const onTapPageChange = () => {
  let params = queryParams.value;
  params.page = state.page.page;
  params.limit = state.page.limit;
  emit('pageChange', params);
}

// 打印
const onPrintTable = () => {
  // https://printjs.crabbly.com/#documentation
  // 自定义打印
  let tableTh = '';
  let tableTrTd = '';
  let tableTd: any = {};
  // 表头
  props.columns.forEach((v) => {
    tableTh += `<th class="table-th">${v.title}</th>`;
  });
  // 表格内容
  props.data.rows.forEach((val, key) => {
    if (!tableTd[key]) tableTd[key] = [];
    props.columns.forEach((v) => {
      if (v.type === 'text') {
        tableTd[key].push(`<td class="table-th table-center">${val[v.key]}</td>`);
      } else if (v.type === 'image') {
        tableTd[key].push(`<td class="table-th table-center"><img src="${val[v.key]}" style="width:${v.width}px;height:${v.height}px;"/></td>`);
      }
    });
    tableTrTd += `<tr>${tableTd[key].join('')}</tr>`;
  });
  // 打印
  printJs({
    printable: `<div style=display:flex;flex-direction:column;text-align:center><h3>${props.config.printName}</h3></div><table border=1 cellspacing=0><tr>${tableTh}${tableTrTd}</table>`,
    type: 'raw-html',
    css: ['//at.alicdn.com/t/c/font_2298093_rnp72ifj3ba.css', '//unpkg.com/element-plus/dist/index.css'],
    style: `@media print{.mb15{margin-bottom:15px;}.el-button--small i.iconfont{font-size: 12px !important;margin-right: 5px;}}; .table-th{word-break: break-all;white-space: pre-wrap;}.table-center{text-align: center;}`,
  });
};


// 导出
const onImportTable = () => {
  if (state.selectlist.length <= 0) return ElMessage.warning('请先选择要导出的数据');
  table2excel(props.columns, state.selectlist, `${themeConfig.value.globalTitle} ${new Date().toLocaleString()}`);
};


// 刷新
const onRefreshTable = () => {
  emit('pageChange', state.page);
};


// 设置
const onSetTable = () => {
  nextTick(() => {
    const sortable = Sortable.create(toolSetRef.value, {
      handle: '.handle',
      dataIdAttr: 'data-key',
      animation: 150,
      onEnd: () => {
        const headerList: EmptyObjectType[] = [];
        sortable.toArray().forEach((val: string) => {
          props.columns.forEach((v) => {
            if (v.key === val) headerList.push({...v});
          });
        });
        emit('sortHeader', headerList);
      },
    });
  });
};


// 暴露变量
defineExpose({
  pageReset,
});


/**************** 表格 END ***********************************************************************************/

</script>


<style scoped lang="scss">
.fly-table-container {
  padding: 20px 10px;
}


.fly-tool-bar {
  display: flex;
  flex-wrap: wrap;
  letter-spacing: 5px;
  padding: 10px;
}



.fly-button-add:hover {
  background-color: #4aacf8;
  letter-spacing: 3px;
}



.fly-el-table-container {
  // padding: 20px 0;
  //border: 1px #f3f3f3 solid;
}

/***** table 样式 *************************************************************************************/
.table-container {
  display: flex;
  flex-direction: column;

  .el-table {
    flex: 1;
  }

  .table-footer {
    display: flex;

    .table-footer-tool {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: flex-end;

      i {
        margin-right: 10px;
        cursor: pointer;
        color: var(--el-text-color-regular);

        &:last-of-type {
          margin-right: 0;
        }
      }
    }
  }
}


.el-pager li {
  margin: 0 !important;
  background: #FFFFFF !important;
}

.fly-pagination {
  padding-left: 10px;
}

.el-table tr {
  height: 45px !important;
}

.el-table__header {
  height: 45px !important;
}


</style>